package search;
import java.io.File;
import java.io.IOException;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.Field.TermVector;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

public final class SearchableIndexer {

	public final static String TAG_FIELD = "tags";
	public final static String ID_FIELD = "Id";
	public final static String NAME_FIELD = "name";
	public final static String DESCRIPTION_FIELD = "description";

	private String indexPath = "";

	public String getIndexPath() {
		return indexPath;
	}

	public void setIndexPath(String indexPath) {
		this.indexPath = indexPath;
	}

	private IndexWriter idxWriter;

	public SearchableIndexer(String indexPath) throws IOException {
		this.indexPath = indexPath;
		Directory idxDir = FSDirectory.open(new File(indexPath));
		StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_36);
		IndexWriterConfig idxWriterConfig = new IndexWriterConfig(
				Version.LUCENE_36, analyzer);
		idxWriterConfig.setOpenMode(OpenMode.CREATE_OR_APPEND);
		idxWriter = new IndexWriter(idxDir, idxWriterConfig);
	}

	private Document extractDocument(ISearchable searchable, String tags){
		Document doc = new Document();
		doc.add(new Field(ID_FIELD, Long.toString(searchable.getId()),
				Store.YES, Index.NOT_ANALYZED, TermVector.NO));
		doc.add(new Field(NAME_FIELD, searchable.getName(), Store.YES,
				Index.ANALYZED, TermVector.YES));
		doc.add(new Field(DESCRIPTION_FIELD, searchable.getDescription(),
				Store.YES, Index.NOT_ANALYZED, TermVector.NO));
		doc.add(new Field(TAG_FIELD, tags + " "
				+ searchable.getDescription() + " "
				+ searchable.getName()
				, Store.NO, Index.ANALYZED,
				TermVector.YES));
		return doc;
	}
	
	public void addSearchable(ISearchable seachable,String tags) throws CorruptIndexException,
			IOException, ParseException {
		Document doc = new Searcher(indexPath).findDocumentById(seachable
				.getId());
		if (doc == null) {
			doc = extractDocument(seachable,tags);
			idxWriter.addDocument(doc);
		}else{
			doc = extractDocument(seachable,tags);
			idxWriter.updateDocument(new Term(ID_FIELD, Long.toString(seachable.getId())), doc);
		}
		
	}
	
	public void updateSearchableTags(long searchableId, String tags) throws CorruptIndexException, IOException, ParseException{
		Searcher searcher = new Searcher(indexPath);
		Document doc = searcher.findDocumentById(searchableId);
		doc.removeField(TAG_FIELD);
		doc.add(new Field(TAG_FIELD, tags + " "
				+ doc.get(DESCRIPTION_FIELD) + " "
				+ doc.get(NAME_FIELD)
				, Store.NO, Index.ANALYZED,
				TermVector.YES));
		idxWriter.updateDocument(new Term(ID_FIELD, doc.get(ID_FIELD)), doc);
	}
	
	public void updateSearchable(ISearchable searchable,String tags) throws CorruptIndexException, IOException{
		Document doc = extractDocument(searchable,tags);
		idxWriter.updateDocument(new Term(ID_FIELD, Long.toString(searchable.getId())), doc);
	}
	

	public void create() throws CorruptIndexException, IOException {
		idxWriter.close();
	}

	@Override
	protected void finalize() throws Throwable {
		super.finalize();
		create();
	}
}
